package com.info.utils;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;

/**
 * @author HAHA
 * 
 */
public class ProtocolUtil {

	/**
	 * 把16进制的时间转换成常规日期时间
	 * 
	 * @param hexDateTime
	 *            终端上来的16进制时间
	 * @return
	 */
	public static String getSimpleFormatDateTime(String hexDateTime) {
		int[] iDateTiem = new int[6];

		for (int j = 1; j <= 6; j++) {
			iDateTiem[j - 1] = Integer.parseInt(
					hexDateTime.substring((j - 1) * 2, j * 2), 16);
		}

		String head = "20";
		if ((iDateTiem[0] + "").length() == 1)
			head = "200";
		return head
				+ iDateTiem[0] + "-" + iDateTiem[1] + "-" + iDateTiem[2] + " "
				+ iDateTiem[3] + ":" + iDateTiem[4] + ":" + iDateTiem[5];
		/*return StringTools.getStrByDate(StringTools.getDateByStr(head
				+ iDateTiem[0] + "-" + iDateTiem[1] + "-" + iDateTiem[2] + " "
				+ iDateTiem[3] + ":" + iDateTiem[4] + ":" + iDateTiem[5]));*/
	}

	
	/**
	 * 将2进制字符串转成16进制字符串
	 * 
	 * @param addInfo
	 *            数据(2进制)
	 * @param length
	 *            目标byte的位数
	 * @return
	 */
	public static String binaryString2HexString(String addInfo, int length) {
		String tenInfo=new BigInteger(addInfo,2).toString();
		int result=Integer.valueOf(tenInfo);
		// 将2个字节补满，左补0
		tenInfo = StringTools.leftAdding(Integer.toHexString(result), "0", length);
		return tenInfo;
	}
	
	/**
	 * 将16进制字符串转成2进制字符串
	 * 
	 * @param addInfo
	 *            数据(16进制)
	 * @param length
	 *            目标byte的位数
	 * @return
	 */
	public static String str2ByteString(String addInfo, int length) {
		// 获得状态位
		int status = Integer.parseInt(addInfo, 16);
		// 转换成字节位
		String str2 = Integer.toBinaryString(status);
		// 将2个字节补满，左补0
		 str2 = StringTools.leftAdding(str2, "0", length);
		return str2;
	}

	public static String hexString2binaryString(String hexString) {
		if (hexString == null || hexString.length() % 2 != 0)
			return null;
		String bString = "", tmp;
		for (int i = 0; i < hexString.length(); i++) {
			tmp = "0000"
					+ Integer.toBinaryString(Integer.parseInt(
							hexString.substring(i, i + 1), 16));
			bString += tmp.substring(tmp.length() - 4);
		}
		return bString;
	}

	/**
	 * 将16进制字符串转成10进制字符串
	 * 
	 * @param addInfo
	 *            数据(16进制)
	 * @param length
	 *            目标byte的位数
	 * @return
	 */
	public static String str2String(String addInfo, int length) {

		StringBuffer result = new StringBuffer("");
		/*List<Integer> array = new ArrayList<Integer>();

		for (int j = 1; j < length + 1; j++) {
			array.add(Integer.parseInt(addInfo.substring((j - 1) * 2, j * 2),
					16));
		}
		for (int i = 0; i < array.size(); i++) {
			//if (array.get(i) > 0) {
				result.append(array.get(i));
			//}
		}*/
		result.append(Integer.parseInt(addInfo,16));
		return result.toString();
	}

	/**
	 * 将16进制ASICC字符串转成16进制字符串
	 * 
	 * @param addInfo
	 *            数据(16进制)
	 * @param length
	 *            目标byte的位数
	 * @return
	 */
	public static String strASICC2String(String addInfo, int length) {

		StringBuffer result = new StringBuffer("");
		List array = new ArrayList();

		for (int j = 1; j < length + 1; j++) {
			array.add((char) Integer.parseInt(
					addInfo.substring((j - 1) * 2, j * 2), 16));
		}
		for (int i = 0; i < array.size(); i++) {
			result.append(array.get(i));
		}
		return result.toString();
	}

	/**
	 * 根据int获取相应的16进制的字符串<br>
	 * 9-> 09,15->0F,补充到指定的长度
	 * 
	 * @param i
	 *            10进制整型数
	 * @param length
	 *            目标16进制数据的长度(1字节是2位)
	 * @return
	 */
	public static String getHexIntString(int i, int length) {
		String str = Integer.toHexString(i);
		if (str.length() < length) {
			// str = StringUtil.lefgPadding(str, '0', length);
		}
		return str.toUpperCase();
	}

	/**
	 * 构造服务器返回数据
	 * 
	 * @param protocolID
	 *            协议号
	 * @param sequenceNum
	 *            信息序号
	 * @return 返回给终端的响应
	 */
	public static String buildResponseString(String protocolID, int sequenceNum) {

		// 内容长度
		String contentLength = "05";
		// 序列号(2字节)
		// 转成16进制
		// log.info("终端上来的序列号:" + sequenceNum);
		String xuliehao = Integer.toHexString(sequenceNum);
		// log.info("返回终端的序列号:" + xuliehao);
		// 补足成4位，2字节
		// xuliehao = StringUtil.lefgPadding(xuliehao, '0', 4);

		// 需要crc校验的位
		String crcString = contentLength + protocolID + xuliehao;
		String crcCode = getCrc16Code(crcString);

		// 组装返回给终端的数据包
		StringBuilder response = new StringBuilder();
		// 包头(2字节)
		// response.append(Gt06ServerConstant.PACKAGE_HEAD_GT06);
		// 内容长度(1字节)
		response.append(contentLength);
		// 协议号(1字节)
		response.append(protocolID);
		// 序列号(2字节)
		response.append(xuliehao);
		// CRC校验码（2字节）
		response.append(crcCode);
		// response.append(Gt06ServerConstant.PACKAGE_END);
		return response.toString();
	}

	/**
	 * 构造服务器返回数据
	 * 
	 * @param protocolID
	 *            协议号
	 * @param sequenceNum
	 *            信息序号
	 * @param content
	 *            信息内容(已经转换成16进制的了)
	 * @return 返回给终端的响应
	 */
	public static String buildResponseString(String protocolID,
			int sequenceNum, String content) {

		int length = 5 + content.length() / 2;

		// 内容长度(1字节)
		String contentLength = getHexIntString(length, 2);
		// 序列号(2字节)
		// 转成16进制
		// log.info("终端上来的序列号:" + sequenceNum);
		String xuliehao = Integer.toHexString(sequenceNum);
		// log.info("返回终端的序列号:" + xuliehao);
		// 补足成4位，2字节
		// xuliehao = StringUtil.lefgPadding(xuliehao, '0', 4);

		// 需要crc校验的位
		String crcString = contentLength + protocolID + content + xuliehao;
		String crcCode = getCrc16Code(crcString);

		// 组装返回给终端的数据包
		StringBuilder response = new StringBuilder();
		// 包头(2字节)
		response.append("7878");
		// 内容长度(1字节)
		response.append(contentLength);
		// 协议号(1字节)
		response.append(protocolID);
		response.append(content);
		// 序列号(2字节)
		response.append(xuliehao);
		// CRC校验码（2字节）
		response.append(crcCode);
		response.append("0D0A");
		return response.toString();
	}

	/**
	 * 16进制字符串获取crc16校验码
	 * 
	 * @param crcString
	 *            终端传过来的16进制的字符串
	 * @return CRC16的校验码
	 */
	public static String getCrc16Code(String crcString) {
		// 转换成字节数组
		byte[] creBytes = Byte2Hex.HexString2Bytes(crcString);

		// 开始crc16校验码计算
		CRC16Util crc16 = new CRC16Util();
		crc16.reset();
		crc16.update(creBytes);
		int crc = crc16.getCrcValue();
		// 16进制的CRC码
		String crcCode = Integer.toHexString(crc);
		// 补足到4位
		if (crcCode.length() < 4) {
			// crcCode = StringUtil.lefgPadding(crcCode, '0', 4);
		}
		return crcCode;
	}

	/**
	 * 将字符串转换成byte数组
	 * 
	 * @param addInfo
	 *            数据(16进制)
	 * @param length
	 *            目标byte的位数
	 * @return
	 */
	public static byte[] decodeStringToBytes(String addInfo, int length) {
		// 获得状态位
		int status = Integer.parseInt(addInfo, 16);
		// 转换成字节位
		String str2 = Integer.toBinaryString(status);
		// 将字节补满，左补0
		// str2 = StringUtil.lefgPadding(str2, '0', length);
		byte[] returnValue = new byte[length];
		for (int i = 0; i < length; i++) {
			returnValue[i] = Byte.parseByte(str2.substring(i, i + 1));
		}
		return returnValue;
	}

	/**
	 * 将字符串转换成60进制的经纬度（度分秒）
	 * 
	 * @param Info
	 *            数据(16进制)
	 * @return
	 */
	public static String parseStringToLLDD(String addInfo) {
		double dd = 0.0;
		// 获得数据
		String info = (Double.parseDouble(Integer.parseInt(addInfo, 16) + "") / 1800000 + "")
				.replace(".", "|");
		dd = Double.parseDouble(info.substring(0, info.indexOf("|")));
		dd += Double.parseDouble("0."
				+ Integer.parseInt(info.substring(info.indexOf("|") + 1,
						info.indexOf("|") + 2)) * 60);
		dd += Double.parseDouble("0.0"
				+ Long.parseLong(info.substring(info.indexOf("|") + 2,
						info.length())) * 60);
		return String.valueOf(dd);
	}

	/**
	 * 构造发送给终端的指令数据包<br>
	 * 
	 * @param content
	 *            指令内容(转换后的16进制字节字符串)k
	 * @param serialNo
	 *            指令流水号(4字节 16进制字符串)
	 * @return
	 */
	public static String buildSendCmdPackage(String content, String serialNo) {

		// 指令流水号 即服务器标志位
		// 包长度 协议号(1字节)+指令长度(1字节) + 指令流水号(4字节)+
		// 内容长度(N)+包序号(2字节)+crc校验(2字节)
		int length = 1 + 1 + 4 + content.length() / 2 + 4;
		StringBuilder sb = new StringBuilder();
		// 包长度
		sb.append(ProtocolUtil.getHexIntString(length, 2));
		// 协议号:80
		sb.append("80");
		// 指令内容长度(指令流水号(4字节)+内容长度(N))
		int contentLen = 4 + content.length() / 2;
		// 指令内容长度：1字节
		sb.append(ProtocolUtil.getHexIntString(contentLen, 2));
		// 指令流水号(4字节)
		sb.append(serialNo);
		// 信息内容
		sb.append(content);
		// 信息序列号(随便写一个)
		sb.append("00A0");
		// CRC校验码
		String crc = ProtocolUtil.getCrc16Code(sb.toString());
		sb.append(crc);
		sb.append("0D0A");
		return "7878" + sb.toString();
	}

	public static void main(String args[]) throws Exception {
		System.out.println(ProtocolUtil.getSimpleFormatDateTime("08090A0E2030"));
		System.out.println(Integer.parseInt("21", 16));
		System.out.println(new Double(Long.parseLong(
				"0C3D909B", 16)) / 1800000 + "");
		String latitude="108.8959909";
		if((latitude.indexOf(".")+6)<latitude.length())
			latitude.substring(0, latitude.indexOf(".")+7);
		System.out.println(ProtocolUtil.binaryString2HexString("00011110", 2));
		System.out.println(ProtocolUtil.str2ByteString("0000001e", 32));
	}
}